#include <bits/stdc++.h>
using namespace std;


struct Substract1
{
    double operator()(double x,double y)
    {
        return x-y;
    }
};

double Substract2(double x,double y)
{
    return x-y;
}

void Test_funtionBag()
{
    //通过包装器，就很好解决了用函数模板去调用不同情况下的

    function<double(double,double)> f1 = Substract1();//相当于穿了个匿名对象去构造
    function<double(double,double)> f2 = &Substract2;//函数名就是地址，取地址与否都可以
    function<double(double,double)> f3 = [](double x,double y){return x-y;};
    cout<<f1(1,2)<<endl;
    cout<<f2(1,2)<<endl;
    cout<<f3(1,2)<<endl;
    return ; 
}




//-----------------------------------------------


class Mut{
    public:
    double Mutd(double a,double b)
    {
        return a*b;
    }
    int Muti(int a,int b)
    {
        return a*b;
    }
};


void MemberFuntion_func()
{
    //成员函数都有this指针，需要你传输过去、
    //成员函数必须取地址传过去
    function<double(Mut*,double,double)> f1 = &Mut::Mutd;
    function<int(Mut*,int,int)> f2 = &Mut::Muti;
    //每次传参都需传成员函数所在类型的指针，但这个指针在只是纯粹使用成员函数时，就很不方便
    cout<<f1((Mut*)nullptr,1,2)<<endl;
    //可以调整参数的顺序和个数，通过bind去实现
    //我们不需要Mut*这个参数，我们就去一开始固定就好了
    //通过placesoders，下标_1，表示之后f3函数里面参数的第几个位置
    //打断点进去可以观看这个现象


    //这个bind后续的顺序，依然是f2参数的顺序，你可以直接传入一个参数进行绑定
    //也可以传入占位符，占位符的数字表示其在新的函数中的参数位置
    function<int(int,int)> f3 = bind(f2,(Mut*)nullptr,placeholders::_2,placeholders::_1);
    cout<<f3(1,2);
}

// 调用bind的一般形式：auto newCallable = bind(callable,arg_list);
// 其中，newCallable本身是一个可调用对象，arg_list是一个逗号分隔的参数列表，对应给定的
// callable的参数。当我们调用newCallable时，newCallable会调用callable,并传给它arg_list中
// 的参数。


int main()
{
    MemberFuntion_func();
    return 0;
}